package com.dding.cms.base.dao.impl;

import static com.dding.cms.base.web.ActionConstants.WIDGET_REMOVE_ID_KEY;
import static com.dding.cms.base.web.ActionConstants.WIDGET_RESULT_KEY;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.dding.core.util.StringUtils;
import org.javalite.activejdbc.Association;
import org.javalite.activejdbc.Model;
import org.javalite.activejdbc.associations.BelongsToAssociation;

import com.dding.cms.base.entity.Content;
import com.dding.cms.base.entity.ContentAttr;
import com.dding.cms.base.web.widget.IWidgetContext;
import com.dding.cms.base.web.widget.IWidgetHandler;
import com.dding.cms.base.web.widget.WidgetContext;
import com.dding.cms.base.web.widget.WidgetUtils;

public class ContentStoreDaoHandler extends
		AbstractDaoHandler<String[], String[]> {

	private static Set<String> columns;
	private Map<String, String[]> rawMap;

	@Override
	public Map<String, String[]> handleField(
			final Map<String, String[]> dataMap, Model model) throws Throwable {

		rawMap = new HashMap<String, String[]>(dataMap);

		columns = WidgetUtils.getContentColumns();
		Iterator<Entry<String, String[]>> it = dataMap.entrySet().iterator();
		while (it.hasNext()) {
			Entry<String, String[]> entry = it.next();
			handleColumnInternalFields(entry, model);
		}
		return dataMap;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Map<String, String[]> handleAssocaition(
			final Map<String, String[]> dataMap, List<Model> list, Model model)
			throws Throwable {

		List<Association> associations = Content.associations();
		for (Association association : associations) {
			if (association instanceof BelongsToAssociation) {
				continue;
			}
			handleInternalAssociation(association.getTarget(), dataMap, list);
		}
		return dataMap;
	}

	@SuppressWarnings("unchecked")
	private void handleInternalAssociation(String targetTable,
			Map<String, String[]> dataMap, List<Model> list) {
		IWidgetHandler handler = controller.getWidgetByTable(targetTable);
		if (handler == null)
			return;
		IWidgetContext widgetContext = new WidgetContext(dataMap);
		logger.debug("handle widget with table" + targetTable);
		Map<String, Object> map = (Map<String, Object>) handler
				.handleSet(widgetContext);
		Object result = map.get(WIDGET_RESULT_KEY);
		if (result instanceof Model) {
			list.add((Model) result);
		} else if (result instanceof List) {
			list.addAll((List<Model>) result);
		}
		List<String> ids = (List<String>) map.get(WIDGET_REMOVE_ID_KEY);
		for (String id : ids) {
			rawMap.remove(id);
		}
	}

	@Override
	public Map<String, String[]> handleExtAttr(
			final Map<String, String[]> dataMap, List<Model> list, Model model)
			throws Throwable {

		Iterator<Entry<String, String[]>> it = rawMap.entrySet().iterator();
		while (it.hasNext()) {
			Entry<String, String[]> entry = it.next();
			handleAttrInternalFields(entry.getKey(), entry.getValue(), list);
		}
		rawMap.clear();
		return dataMap;
	}

	private boolean handleAttrInternalFields(String key, String[] value,
			List<Model> list) {

		String[] name = WidgetUtils.parserName(key);

		if (name != null && name.length == 1) {

			if (columns.contains(key)) {
				return false;
			}
			if (value != null && value.length != 0
					&& StringUtils.isNotEmpty(value[0])) {
				list.add(createAttrModel(key, value[0]));
			}

		} else if (name != null && name.length == 2) {

			if (columns.contains(name[0])) {
				return false;
			}

			IWidgetHandler handler = controller.getWidgetByTypeAndName(name[1],
					name[0]);
			if (handler == null) {
				logger.debug("find no widget handler with " + name[1]);
				list.add(createAttrModel(name[0], value[0]));
			} else {
				logger.debug("handler field" + name[1] + " deal with " + key);
				Map<String, String[]> map = new HashMap<String, String[]>();
				map.put(name[0], value);
				IWidgetContext widgetContext = new WidgetContext(map);
				Object result = handler.handleSet(widgetContext);
				if (result instanceof String[]) {
					String[] temp = (String[]) result;
					list.add(createAttrModel(temp[0], temp[1]));
				}
			}
		}
		return true;
	}

	private Model createAttrModel(String key, String value) {
		ContentAttr attr = new ContentAttr();
		attr.set("attr_name", key);
		attr.set("attr_value", value);
		return attr;
	}

	private boolean handleColumnInternalFields(Entry<String, String[]> entry,
			Model model) {

		String[] name = WidgetUtils.parserName(entry.getKey());

		String[] value = entry.getValue();
		if (name != null && name.length == 1) {

			if (!columns.contains(entry.getKey())) {
				return false;
			}
			if (value != null && value.length != 0
					&& StringUtils.isNotEmpty(value[0])) {
				model.set(entry.getKey(), value[0]);
			}

		} else if (name != null && name.length == 2) {

			if (!columns.contains(name[0])) {
				return false;
			}

			IWidgetHandler handler = controller.getWidgetByTypeAndName(name[1],
					name[0]);
			if (handler == null) {
				logger.debug("find no widget handler with " + name[1]);
				model.set(name[0], value[0]);
			} else {
				logger.debug("handler field" + name[1] + " deal with "
						+ entry.getKey());
				Map<String, String[]> map = new HashMap<String, String[]>();
				map.put(name[0], entry.getValue());
				IWidgetContext widgetContext = new WidgetContext(map);
				Object result = handler.handleSet(widgetContext);
				if (result instanceof String[]) {
					String[] temp = (String[]) result;
					model.set(temp[0], temp[1]);
				}
			}
		}
		rawMap.remove(entry.getKey());
		return true;
	}

}
